#include "Combination.h"
#include "Tokenizer.h"
namespace Pomian
{
	Sequence::Sequence(const std::list<IParser*>& parsers, const std::function<AstNode* (const std::vector<AstNode*>&)>& combine)
		: m_parsers(parsers)
		, m_combine(combine)
	{
	}
	AstNode* Sequence::parse(Tokenizer* tokenizer)
	{
		std::vector<AstNode*> nodes;
		tokenizer->redo();
		for (IParser* parser : m_parsers)
		{
			AstNode *ast = parser->parse(tokenizer);
			if (ast == nullptr)
			{
				tokenizer->undo();
				return nullptr;
			}
			nodes.push_back(ast);
		}
		return m_combine(nodes);
	}
	Sequence::~Sequence()
	{
		for (IParser *parser : m_parsers)
		{
			delete parser;
		}
		m_parsers.clear();
	}
	Or::Or(const std::list<IParser*>& parsers)
		: m_parsers(parsers)
	{
	}
	AstNode* Or::parse(Tokenizer* tokenizer)
	{
		tokenizer->redo();
		for (IParser* parser : m_parsers)
		{
			AstNode* ast = parser->parse(tokenizer);
			if (ast != nullptr)
			{				
				return ast;
			}
			tokenizer->undo();
		}
		return nullptr;
	}
	Or::~Or()
	{
		for (IParser* parser : m_parsers)
		{
			delete parser;
		}
		m_parsers.clear();
	}

	Repeat::Repeat(IParser* parser)
		: m_parser(parser)
	{
	}
	AstNode* Repeat::parse(Tokenizer* tokenizer)
	{
		ListNode* lst = new ListNode();		
		do
		{
			tokenizer->redo();
			AstNode* node = m_parser->parse(tokenizer);
			if (node == nullptr)
			{
				tokenizer->undo();
				break;
			}
			lst->addChild(node);
		} while (true);
		return lst;
	}
	Repeat::~Repeat()
	{
		delete m_parser;
	}
	
	Option::Option(IParser* parser)
		: m_parser(parser)
	{
	}
	AstNode* Option::parse(Tokenizer* tokenizer)
	{
		tokenizer->redo();
		AstNode* node = m_parser->parse(tokenizer);
		if (node == nullptr)
		{
			tokenizer->undo();
			return NullStmnt::Null;
		}
		return node;
	}
	Option::~Option()
	{
		delete m_parser;
	}
}